iT邦幫忙

2022 iThome 鐵人賽

DAY 18
0
Modern Web

開始搞懂React生態系系列 第 18

Day 18 多層級元件間的狀態管理 - Context & useContext

  • 分享至 

  • xImage
  •  

多層級元件的資料傳遞

一層一層的傳遞 props 至需要使用的元件

上層元件要傳給子層元件資料,是用 props 來傳遞,若子層元件有很多層,而最底層元件需要該資料,無論中間的元件有沒有使用到,都必需一層一層的傳 props。

const App = () => {
  const [user, setUser] = React.useState("Lala");

  return (
    <>
      <h1>{`Hello ${user}!`}</h1>
      <Component1 user={user} />
    </>
  );
};

const Component1 = ({ user }) => {
  return (
    <>
      <h1>Component 1</h1>
      <Component2 user={user} />
    </>
  );
};

const Component2 = ({ user }) => {
  return (
    <>
      <h1>Component 2</h1>
      <Component3 user={user} />
    </>
  );
};

const Component3 = ({ user }) => {
  return (
    <>
      <h1>Component 3</h1>
      <h2>{`Hello ${user} again!`}</h2>
    </>
  );
};

每層傳遞 props,就算 Componet1 跟 Componet2 用不到
也必需層層傳遞 props 至需要使用的 Component3

  • 執行結果:https://codepen.io/lala-lee-jobs/pen/xxjLKLX?editors=0011

改用 React Context API

透過 Context 的概念,可以將資料傳到直接傳送到需要的元件,而不需要手動一直透過 props 傳入。

  • Context 是設計來在 React 元件中共享資料。
  • Context 主要用在當多個不同嵌套層級的元件要用到相同的資料時才會只用,除此之外,應該盡量避免使用,因為它會使得元件更難被重用。
  • 使用 Context 之後,在 Context 範圍內的元件,不管隔幾層都可以取得該 Context 提供的資料。

使用 Context API 有三個步驟

  1. 建立 Context 物件內容
const xxxContext = createContext();
  1. 提供 Context Provider (Provider 內建於 Context 中)
<xxxContext.Provider value={要給Context範圍內元件使用的值}>
  ...
</xxxContext.Provider>
  1. 在 Function Component 中使用 Context - useContext
const data = useContext(xxxContext);

使用 Context API 改寫上面的範例

Step 1. 建立 Context 物件內容

const UserContext = createContext();

Step 2. 提供 Context Provider,把要使用 Context 資訊的元件使用 <xxxContext.Provider> 包起來

這邊要傳的是資料是 user,所以 value 放的是 user

const App = () => {
  const [user, setUser] = useState("lala");

  return (
    <UserContext.Provider value={user}>
      <h1>{`Hello ${user}!`}</h1>
      <Component2 />
    </UserContext.Provider>
  );
}

Step 3. 在 Function Component 中使用 Context - useContext

const Component3 = () => {
  const user = useContext(UserContext);

  return (
    <>
      <h1>Component 5</h1>
      <h2>{`Hello ${user} again!`}</h2>
    </>
  );
}

完整組合如下

const UserContext = React.createContext();

const App = () => {
  const [user, setUser] = React.useState("lala");

  return (
    <UserContext.Provider value={user}>
      <h1>{`Hello ${user}!`}</h1>
      <Component2 />
    </UserContext.Provider>
  );
}

const Component1 = ({ user }) => {
  return (
    <>
      <h1>Component 1</h1>
      <Component2 />
    </>
  );
};

const Component2 = ({ user }) => {
  return (
    <>
      <h1>Component 2</h1>
      <Component3 />
    </>
  );
};

const Component3 = () => {
  const user = React.useContext(UserContext); 
  return (
    <>
      <h1>Component 3</h1>
      <h2>{`Hello ${user} again!`}</h2>
    </>
  );
};
  • 執行結果:https://codepen.io/lala-lee-jobs/pen/rNvzaLb?editors=0011

Context 的使用情境

Context 有一個致命的缺點,當 Context 資料更新時,會讓所有在 Context 範圍內中的元件都會 Re-Render,所以不會經常變動的內容才比較使用 Context 來做資料的共享。像是「使用者的登入狀態」、「樣式(theme)」、「語系切換(preferred language)」等。

Next

如果我們希望元件之間共享資料,使用 props 層層傳遞太麻煩,而使用 Context 又會有效能上的問題,那還有什麼方式可以達成?

在大型的應用上,都會引入 Redux 這個第三方提供的狀態管理套件來操作。接下來會開始深入探討 Redux 這個主題。

Reference

https://www.w3schools.com/react/react_usecontext.asp

https://pjchender.dev/react/react-doc-context/

https://medium.com/hannah-lin/react-hook-%E7%AD%86%E8%A8%98-usecontext-4bc289976847


上一篇
Day 17 初探狀態管理 - Flux 架構 與 useReducer
下一篇
Day 19 全站狀態管理的利器 - Redux (一) Store and Action
系列文
開始搞懂React生態系30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言